﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WebCrawler
{
    public partial class Crawler : Form
    {
        private IHTMLDocGraph graph;
        private List<IHTMLDoc> visited = new List<IHTMLDoc>();

        public Crawler()
        {
            InitializeComponent();
        }

        private void buttonGo_Click(object sender, EventArgs e)
        {
            if (buttonGo.Text == "Start")
            {
                buttonGo.ForeColor = Color.Red;
                buttonGo.Text = "Stop";
                progressBarWait.MarqueeAnimationSpeed = 10;
                treeViewPages.Nodes.Clear();
                graph = new HTMLDocGraph(textBoxUrl.Text);
                backgroundWorkerCrawl.RunWorkerAsync();
            }
            else
            {
                backgroundWorkerCrawl.CancelAsync();
                stop();
            }
        }

        private void stop()
        {
            buttonGo.ForeColor = Color.Green;
            buttonGo.Text = "Start";
            progressBarWait.MarqueeAnimationSpeed = 0;
            progressBarWait.Refresh();
        }

        private void crawl()
        {
            IHTMLDoc htmlDoc = null;
            while ((htmlDoc = graph.GetNextUnvisitedDoc()) != null)
            {
                htmlDoc.downloadPage();
                graph.Add(htmlDoc);
            }
        }

        private TreeNode TraversMap(IHTMLDoc htmlDoc)
        {
            TreeNode node = new TreeNode(htmlDoc.URL);
            node.Tag = htmlDoc;
            visited.Add(htmlDoc);
            foreach (IHTMLDoc d in graph.GetChildren(htmlDoc))
            {
                if (!visited.Contains(d))
                    node.Nodes.Add(TraversMap(d));
                else
                {
                    /* If node HTML already visited, we want to show it in a
                     * tree, but do not traverse it deeper. */
                    TreeNode childNode = new TreeNode(d.URL);
                    childNode.ImageIndex = 1;
                    childNode.SelectedImageIndex = 1;
                    childNode.Tag = d;
                    node.Nodes.Add(childNode);
                }
            }

            return node;
        }

        private void treeViewPages_AfterSelect(object sender, TreeViewEventArgs e)
        {
            IHTMLDoc doc = (IHTMLDoc)treeViewPages.SelectedNode.Tag;

            webBrowserView.DocumentText = doc.Document;
            textBoxSource.Text = doc.Document;
        }

        private void buttonSearch_Click(object sender, EventArgs e)
        {
            FindInTreeView(treeViewPages.Nodes, textBoxSearch.Text);
        }

        private void FindInTreeView(TreeNodeCollection tncoll, string strNode)
        {
            foreach (TreeNode tnode in tncoll)
            {
                IHTMLDoc doc = (IHTMLDoc)tnode.Tag;
                if ((doc.Document.ToLower().Contains(strNode.ToLower())) && (strNode != "") && (tnode.ImageIndex != 1))
                {
                    tnode.ForeColor = Color.Green;
                    tnode.TreeView.SelectedNode = tnode;
                }
                else
                {
                    tnode.ForeColor = SystemColors.WindowText;
                }
                FindInTreeView(tnode.Nodes, strNode);
            }
        }

        private void backgroundWorkerCrawl_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                crawl();
            }
            catch
            {
                MessageBox.Show("Please check:\n\n• If your internet connection is working\n• The address for typing errors", "Server not found", MessageBoxButtons.OK, MessageBoxIcon.Information);
                graph = null;
            }
        }

        private void backgroundWorkerCrawl_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (graph != null)
            {
                treeViewPages.Nodes.Add(TraversMap(graph.getRootDoc()));
                treeViewPages.ExpandAll();
            }
            stop();
        }
    }
}
